/*
 * Digital Audio Mobile - A multi track studio for Windows Mobile
 * Copyright (C) 2008 David Olsson
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

#include "AudioBuffer.h"
#include "Dialog.h"
#include "Segment.h"

Segment::Segment(const MusicTime &pos) throw(): m_pos(pos), m_wavFile(0), m_hFile(INVALID_HANDLE_VALUE), m_buffer(0) {
}

Segment::~Segment() {
    if(m_buffer != 0) {
        delete(m_buffer);
    }
    if(m_hFile != INVALID_HANDLE_VALUE) {
        CloseHandle(m_hFile);
    }
    if(m_wavFile != 0) {
        delete[](m_wavFile);
    }
}

void Segment::setPosition(const MusicTime &pos) throw() {
    m_pos = pos;
}

void Segment::setSource(const TCHAR *wavFile) throw() {
    if(m_wavFile != 0) {
        delete[](m_wavFile);
        m_wavFile = 0;
    }

    m_wavFile = new TCHAR[_tcslen(wavFile) + 1];
    _tcscpy(m_wavFile, wavFile);
}

void Segment::setFileLength(const MusicTime &length) throw() {
    m_length = length;
}

void Segment::setFileOffset(const MusicTime &offset) throw() {
    m_offset = offset;
}

void Segment::superPositionToAudioBuffer(AudioBuffer *buffer, const MusicTime &bufferStart) const throw() {
    if(m_hFile == INVALID_HANDLE_VALUE) {
        openSourceFile();
    }

    if(m_hFile != INVALID_HANDLE_VALUE) {
        readDataIntoBuffer(bufferStart);
        buffer->superPosition(*m_buffer);
    }
}

void Segment::paint(HDC hDc, HBRUSH hBrush, const RECT &rect, const MusicTime &viewStart, const MusicTime &viewEnd) const throw() {
    RECT segRect = rect;
    segRect.left = ((rect.right - rect.left) * (m_pos - viewStart).toMilliseconds()) / (viewEnd - viewStart).toMilliseconds();
    segRect.right = ((rect.right - rect.left) * ((m_pos + m_length) - viewStart).toMilliseconds()) / (viewEnd - viewStart).toMilliseconds();
    if((rect.bottom - rect.top) >= Dialog::heightToPixels(6)) {
        segRect.top += Dialog::heightToPixels(2);
        segRect.bottom -= Dialog::heightToPixels(2);
    }
    FillRect(hDc, &segRect, hBrush);

    MoveToEx(hDc, segRect.left, segRect.top, 0);
    LineTo(hDc, segRect.right, segRect.top);
    LineTo(hDc, segRect.right, segRect.bottom);
    LineTo(hDc, segRect.left, segRect.bottom);
    LineTo(hDc, segRect.left, segRect.top);
}

void Segment::openSourceFile() const throw() {
    ASSERT(m_hFile == INVALID_HANDLE_VALUE);

    if((m_hFile = CreateFile(m_wavFile, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
        // Read the wave file header.
        DWORD bytesRead;
        RiffHeader rh;
        ReadFile(m_hFile, &rh, sizeof(RiffHeader), &bytesRead, 0);
        if(bytesRead != sizeof(RiffHeader) || rh.riff[0] != 'R' || rh.riff[1] != 'I' || rh.riff[2] != 'F' || rh.riff[3] != 'F' || rh.wave[0] != 'W' || rh.wave[1] != 'A' || rh.wave[2] != 'V' || rh.wave[3] == 'E') {
            CloseHandle(m_hFile);
            m_hFile = INVALID_HANDLE_VALUE;
            return;
        }
        // Read the format header.
        FormatHeader fh;
        ReadFile(m_hFile, &fh, sizeof(FormatHeader), &bytesRead, 0);
        if(bytesRead != sizeof(FormatHeader) || fh.fmt[0] != 'f' || fh.fmt[1] != 'm' || fh.fmt[2] != 't' || fh.fmt[3] != ' ' || fh.format != 1 || fh.numChannels != 1 || (fh.sampleRate != 11025 && fh.sampleRate != 22050 && fh.sampleRate != 44100) || fh.bitsPerSample > 16) {
            CloseHandle(m_hFile);
            m_hFile = INVALID_HANDLE_VALUE;
            return;
        }
        // Read the data header.
        DataHeader dh;
        ReadFile(m_hFile, &dh, sizeof(DataHeader), &bytesRead, 0);
        if(bytesRead != sizeof(DataHeader) || dh.data[0] != 'd' || dh.data[1] != 'a' || dh.data[2] != 't' || dh.data[3] != 'a') {
            CloseHandle(m_hFile);
            m_hFile = INVALID_HANDLE_VALUE;
            return;
        }

        // Remeber where in the file the actual data starts.
        m_dataStart = SetFilePointer(m_hFile, 0, 0, FILE_CURRENT);
        // And create an audio buffer to store the file data in.
        m_buffer = new AudioBuffer(8192, fh.numChannels, fh.sampleRate, fh.bitsPerSample / 8);
    }
}

void Segment::readDataIntoBuffer(const MusicTime &time) const throw() {
}
